<?php

namespace App\Modules\Admin\Services\Water\Tools;

use App\Exceptions\Exception;

class CryptAES
{
    const  DEFAULT_CACHE_TIME=86400;
    /**
     * var string $method 加解密方法，可通过openssl_get_cipher_methods()获得
     */
    protected  $method;

    /**
     * var string $secret_key 加解密的密钥
     */
    protected  $secret_key;

    /**
     * var string $iv 加解密的向量，有些方法需要设置比如CBC
     */
    protected  $iv;

    /**
     * var string $options （
     */
    protected  $options;

    /**
     * 构造函数
     *
         * @param string $key 密钥
     * @param string $method 加密方式
     * @param string $iv iv向量
     * @param mixed $options
     * @throws Exception
     */
    public function __construct(
        string $key, string $method = 'aes-256-ecb', string $iv = '',  $options = OPENSSL_RAW_DATA)
    {
        // key是必须要设置的
        if(!$key) {
            throw new Exception('key不存在');
        }
        $this->secret_key = $key;

        $this->method = $method;

        $this->iv = $iv;

        $this->options = $options;
    }

    /**
     * 加密方法，对数据进行加密，返回加密后的数据
     *
     * @param string $data 要加密的数据
     *
     * @return string
     *
     */
    public function encrypt(string $data): string
    {
        return openssl_encrypt($data, $this->method, $this->secret_key, $this->options);
    }

    /**
     * 解密方法，对数据进行解密，返回解密后的数据
     *
     * @param string $data 要解密的数据
     *
     * @return string
     *
     */
    public function decrypt(string $data): string
    {
        return openssl_decrypt($data, $this->method, $this->secret_key, $this->options);
    }

    /**
     * @param $tokenData
     * @param $type
     * @return string
     * @throws Exception
     */
    public static function createToken($tokenData,$type): string
    {
        $data = [
            'data' => $tokenData,
            'exp_data' => time() + self::DEFAULT_CACHE_TIME,
            'version' => config('init.version')
        ];
        try {
            $res = (new CryptAES(config("auth.safe_key.$type")))->encrypt(json_encode($data));
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return base64_encode($res);
    }

    /**
     * @param $token
     * @param $type
     * @return mixed
     * @throws Exception
     */
    public static function decryptToken($token,$type): mixed
    {
        $token = base64_decode(str_replace(' ', '+', $token));
        try {
            $res = (new CryptAES(config("auth.safe_key.$type")))->decrypt($token);
            if (!empty($res)) {
                return json_decode($res, true);
            }
            return $res;
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }

    }

}
